#include <iostream>
#include <string>
#include <map>
#include "../../libpland/lib/plugin.hpp"
#include <openssl/md5.h>
#include <unistd.h>
#include <stdlib.h>

using namespace std;

using namespace pland;

class Loader : public UserC_Plugin
{
public:
    Loader();
    ~Loader();
    void start();
    void stop();
    void load_queues(SharedDQueue front ,SharedDQueue back);
    void setId(int id);
private:
    SharedDQueue front_;
    SharedDQueue back_;
    bool running_;
    int id_;
};


Loader::Loader()
{
    running_ = false;

}

void Loader::setId(int id)
{
    id_ = id;
    Settings *set  = Settings::Instance();
    std::string regName = "Loader" + utill_to_string(id);
    set->setSetting(regName + ".passes","1");
    set->setSetting(regName + ".fraction","1.0");
}

void Loader::start()
{
    utill_log("Pluggin Loader Started ID:" + utill_to_string(id_));
    running_ = true;
    Settings *set  = Settings::Instance();
    std::string regName = "Loader" + utill_to_string(id_);
    int count = 0;
    int passes = utill_to_int(set->getSetting(regName + ".passes"));
    float fraction = utill_to_int(set->getSetting(regName + ".fraction"));
    unsigned char result[MD5_DIGEST_LENGTH];
    while(running_)
    {
        if(count%10 == 0)
        {
            passes = utill_to_int(set->getSetting(regName + ".passes"));
            fraction = utill_to_int(set->getSetting(regName + ".fraction"));
        }
        SharedData source = front_->pop();
        for(int i = 0; i< passes; i++)
        {
            MD5((unsigned char*)source->get_data(), source->get_header()->size, result);
        }
        if(source->get_header()->size*fraction < 1)
        {
            back_->push(source);
            continue;
        }
        char* data = new char[(int)(source->get_header()->size*fraction)];
        Data_Header* header = new Data_Header;
        ::memmove((char*)header,source->get_header(), sizeof(Data_Header));
        header->size = (int)(source->get_header()->size*fraction);
        SharedData next(new Data(data, header));
        back_->push(next);
    }
}

void Loader::stop()
{
    running_ = false;
}

void Loader::load_queues(SharedDQueue front ,SharedDQueue back)
{
    front_  = front;
    back_  = back;
}


extern "C"
{

UserC_Plugin* Core_GetInstance()
{
    return new Loader();
}

void Core_KillInstance(UserC_Plugin* a)
{
    delete dynamic_cast<Loader*>(a);
}

}
